﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Wise.TimeWarrior.DTO;

namespace Wise.TimeWarrior.Business.Impl
{
    /// <summary>
    /// <see cref="IApplicationLogic"/>
    /// </summary>
    public class ApplicationLogic : IApplicationLogic
    {

        #region IApplicationLogic

        /// <summary>
        /// <see cref="IApplicationLogic.BusinessLogics"/>
        /// </summary>
        public Dictionary<string, object> BusinessLogics
        {
            set;
            get;
        }

        /// <summary>
        /// <see cref="IApplicationLogic.MenuItemsNamesDictionary"/>
        /// </summary>
        public Dictionary<string, string> MenuItemsNamesDictionary
        {
            set;
            get;
        }

        /// <summary>
        /// <see cref="IDisposable.Dispose"/>
        /// </summary>
        public void Dispose()
        {
            foreach (var bl in BusinessLogics)
            {
                if (bl.Value is IDisposable)
                {
                    ((IDisposable)bl.Value).Dispose();
                }
            }
        }

        /// <summary>
        /// <see cref="IBLSetup.SetupLogic"/>
        /// </summary>
        public void SetupLogic()
        {
            foreach (var bl in BusinessLogics)
            {
                if (bl.Value is IBLSetup)
                {
                    ((IBLSetup)bl.Value).SetupLogic();
                }
            }
        }


        /// <summary>
        /// <see cref="IApplicationLogic"/>
        /// </summary>
        public IEnumerable<BusinessItemDto> GetAllLogics()
        {
            List<BusinessItemDto> items = ProcessBusinessItems(GetAllBusinessItemsFromBusinessLogics());

            return items.Where(p => p.ActionOption == BusinessItemOption.Visible || p.ActionOption == BusinessItemOption.AutoRunVisible);
        }
        #endregion IApplicationLogic


        #region AppBasicFunctionality
        /// <summary>
        /// method returns application close functionality
        /// </summary>
        /// <returns></returns>
        private static BusinessItemDto ApplicationExitFunctionality()
        {
            return new BusinessItemDto()
            {
                ActionOption = BusinessItemOption.Visible,
                OriginalMethodName = @"Exit",
                Action = () => Application.Exit(),
            };
        }
        #endregion AppBasicFunctionality


        /// <summary>
        /// Method retrievs from business logics dictionary functionalities
        /// </summary>
        /// <returns>List of business items available from menu window</returns>
        private List<BusinessItemDto> GetAllBusinessItemsFromBusinessLogics()
        {
            List<BusinessItemDto> items = new List<BusinessItemDto>();

            foreach (var bl in BusinessLogics)
            {
                MethodInfo[] methodInfos = bl.Value.GetType().GetMethods();

                foreach (var mi in methodInfos)
                {
                    if (mi.ReturnType == typeof(BusinessItemDto))
                    {
                        BusinessItemDto menuItem = GetBusinessItem(bl, mi);
                        items.Add(menuItem);
                    }
                }
            }

            items.Add(ApplicationExitFunctionality());

            return items;
        }
        /// <summary>
        /// Method processes business items , if item is autorunable will be here started. 
        /// </summary>
        /// <param name="businessLogicItems"></param>
        /// <returns></returns>
        private List<BusinessItemDto> ProcessBusinessItems(List<BusinessItemDto> businessLogicItems)
        {
            foreach (var item in businessLogicItems)
            {
                TranslateMethodName(item);
                RunAutoRunableMethod(item);
            }

            return businessLogicItems;
        }

        private static BusinessItemDto GetBusinessItem(KeyValuePair<string, object> bl, MethodInfo mi)
        {
            BusinessItemDto menuItem = (BusinessItemDto)(mi.Invoke(bl.Value, null));
            menuItem.OriginalMethodName = mi.Name;
            return menuItem;
        }
        /// <summary>
        /// method translates items in menu
        /// </summary>
        /// <param name="menuItem"></param>
        private void TranslateMethodName(BusinessItemDto menuItem)
        {
            if (MenuItemsNamesDictionary.ContainsKey(menuItem.OriginalMethodName))
            {
                menuItem.TranslatedActionName = MenuItemsNamesDictionary[menuItem.OriginalMethodName];
            }
        }
        /// <summary>
        /// method invoke auto runable items
        /// </summary>
        /// <param name="menuItem"></param>
        private static void RunAutoRunableMethod(BusinessItemDto menuItem)
        {
            if (menuItem.ActionOption == BusinessItemOption.AutoRunHidden || menuItem.ActionOption == BusinessItemOption.AutoRunVisible)
            {
                menuItem.Action.Invoke();
            }
        }


    }
}
